<?php
/** 
 * EGP Framework
 *
 * LICENSE
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author     Akon(番茄红了) <aultoale@gmail.com>
 * @copyright  Copyright (c) 2008 (http://www.tblog.com.cn)
 * @license    http://www.gnu.org/licenses/gpl.html     GPL 3
 */

!defined('EGP_LIB_DIR') && die('Access Deny!');

/**
 * Controller 前端控制器
 *
 * @package    classes
 * @author     Akon(番茄红了) <aultoale@gmail.com>
 * @copyright  Copyright (c) 2008 (http://www.tblog.com.cn)
 * @license    http://www.gnu.org/licenses/gpl.html     GPL 3
 */
class EGP_Controller_Front
{

    const NOT_FOUND_MODULE = '模块 %s 不存在';
    const NOT_FOUND_CTRL   = '模块 %s 下的控制器 %s 不存在';
    const NOT_FOUND_ACTION = '模块 %s 下的控制器 %s 不存在 %s 方法';

    /**
     * 存储单件模式实例
     *
     * @var EGP_Controller_Front
     */
    private static $_instance = null;

    /**
     * 存储被加载的模块数组
     *
     * @var array
     */
    private $_modules = array();

    /**
     * 默认模块名称
     *
     * @var string
     */
    private $_defaultModule = 'default';

    /**
     * 最后被运行的 Controller 实例
     *
     * @var EGP_Controller_Action
     */
    private $_lastController = null;

    /**
     * 是否已经完成 Controller 运行
     *
     * @var boolean
     */
    protected $_isDispatched = false;

    /**
     * 单件模式调用方法
     *
     * @return EGP_Controller_Front
     */
    public static function getInstance()
    {
        if (!self::$_instance instanceof self)
            self::$_instance = new self();
        return self::$_instance;
    }

    /**
     * 构造方法
     */
    private function __construct()
    {
        $this->getRouter()->resetInstance();
    }

    /**
     * clone 魔术方法
     */
    final private function __clone()
    {}

    /**
     * 添加模块
     *
     * @param  string  $name     模块名称
     * @param  mixed   $options  配置选项
     * @return EGP_Controller_Front
     */
    public function addModule($name, $options)
    {
        $name = strtolower($name);
        $module = new EGP_Controller_Module($name);
        ($options instanceof EGP_ArrayObject) && $options = $options->toArray();
        $module->setOptions($options);
        $this->_modules[$name] = $module;
        return $this;
    }

    /**
     * 是否存在指定模块
     *
     * @param  string  $name  模块名称
     * @return boolean
     */
    public function hasModule($name)
    {
        $name = strtolower($name);
        return isset($this->_modules[$name]);
    }

    /**
     * 获取模块实例
     *
     * @param  string  $name  模块名称
     * @return EGP_Controller_Module|false
     */
    public function getModuleInstance($name)
    {
        $name = strtolower($name);
        return $this->hasModule($name) ? $this->_modules[$name] : false;
    }

    /**
     * 获取所有已加载的模块
     *
     * @return array
     */
    public function getModuleList()
    {
        return $this->_modules;
    }

    /**
     * 设置默认模块名称
     *
     * @param  string  $name  模块名称
     * @return EGP_Controller_Front
     * @throws EGP_Exception
     */
    public function setDefaultModule($name)
    {
        if (!$this->hasModule($name))
            throw new EGP_Exception("模块 '$name' 不存在，无法设定为默认");
        if (empty($name))
            throw new EGP_Exception("默认模块名称不允许为空");
        $this->_defaultModule = strtolower($name);
        return $this;
    }

    /**
     * 获取默认模块名称
     *
     * @return string
     * @throws EGP_Exception
     */
    public function getDefaultModule()
    {
        if (!$this->hasModule($this->_defaultModule)) {
            if (empty($this->_modules))
                throw new EGP_Exception("尚未添加任何模块，项目无法运行");
            reset($this->_modules);
            $this->setDefaultModule(current($this->_modules));
        }
        return $this->_defaultModule;
    }

    /**
     * 获取 EGP_Controller_Router 实例
     *
     * @return EGP_Controller_Router
     */
    public function getRouter()
    {
        return EGP_Controller_Router::getInstance();
    }

    /**
     * 前往指定的 action-controller-module
     *
     * @param  string  $actionName
     * @param  string  $controllerName
     * @param  string  $moduleName
     * @return EGP_Controller_Action
     */
    public function forward($actionName, $controllerName, $moduleName)
    {
        //设置参数
        EGP_Http_Request::getInstance()->setParams(array(
            'module' => $moduleName,
            'controller' => $controllerName,
            'action' => $actionName,
        ));

        //获取Module
        if (!$this->hasModule($moduleName))
            EGP_Http::_404(sprintf(self::NOT_FOUND_MODULE, $moduleName));
        $module = $this->getModuleInstance($moduleName);
        EGP_Core::setIncludePath($module->getModelDirectory());

        //载入Controller
        $class = ucfirst($controllerName) . 'Controller';
        if (!EGP_Core::classExists($class, $module->getControllerDirectory()))
            EGP_Http::_404(sprintf(self::NOT_FOUND_CTRL, $moduleName, $controllerName));

        //实例化Controller
        $controller = new $class();
        if (!$controller instanceof EGP_Controller_Action)
            throw new EGP_Exception("$class 必须从 EGP_Controller_Action 继承");
        $this->_lastController = $controller;
        $controller->init();
        $controller->{$actionName . 'Action'}();

        //结束运行
        if ($this->isDispatched() === false) {
            $controller->dispatch();
            $this->_isDispatched = true;
            exit();
        }

        return $controller;
    }

    /**
     * 获取最后运行的 Controller
     *
     * @return EGP_Controller_Action
     */
    public function lastController()
    {
        return $this->_lastController;
    }

    /**
     * 是否已经完成 Controller 运行
     *
     * @return boolean
     */
    public function isDispatched()
    {
        return $this->_isDispatched;
    }

    /**
     * 获取到参数并发送到 EGP_Controller_Action 运行
     *
     * @return EGP_Controller_Action
     */
    public function dispatch()
    {
        //获取到所有参数
        $params = $this->getRouter()->parseParams();
        $this->forward($params['action'], $params['controller'], $params['module']);
    }

}